using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Possan.Graphics.Filters
{
	/// <summary>
	/// A fast gaussian like blur filter
	/// </summary>
	public class BlurFilter : IBaseFilter
	{
		/// <summary>
		/// Blur radius in pixels
		/// </summary>
		public int Radius;

		/// <summary>
		/// Expand image to fit blurred image
		/// </summary>
		public bool Expand;

		public string ParameterDefinition
		{
			get
			{
				return null;
			}
		}


		public BlurFilter()
		{
			Radius = 5;
			Expand = true;
		}

		public Bitmap Filter(Bitmap bmp)
		{

			if (bmp.Width * bmp.Height < 400 * 300)	 // lite säkerhetskoll, kör inte blurr på för stora bilder
			{

				int Radius2 = Radius * 2;

				int nw = bmp.Width;
				int nh = bmp.Height;// +Radius2 * 2;

				if (Expand)
				{
					nw += Radius2 * 2;
					nh += Radius2 * 2;
				}

				System.Drawing.Graphics g1 = System.Drawing.Graphics.FromImage(bmp);

				Bitmap bmp2 = Utilities.NewBitmap(nw, nh);
				bmp2.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
						  
				int imgx = 0;
				int imgy = 0;
				if (Expand)
				{
					imgx = Radius2;
					imgy = Radius2;
				}		 

				int samples = Radius2 * Radius2;
				int[] usamp = new int[samples];
				int[] vsamp = new int[samples];
				float[] weight = new float[samples];
				Random r = new Random();
				int s = 0;
				for (int s1 = 0; s1 < Radius2;  s1++)
				{
					for (int s2 = 0; s2 < Radius2 ;  s2++)
					{
						float dx = ((s2 / (float)Radius2) * 1.0f) - 0.5f;
						float dy = ((s1 / (float)Radius2) * 1.0f) - 0.5f;

						// (s2 * 2) - s2;// (float)((r.NextDouble() * 2.0) - 1.0);
						// 1 (s1 * 2) - s1;// (float)((r.NextDouble() * 2.0) - 1.0);

						float x = (float)Radius * dx;
						float y = (float)Radius * dy;

						usamp[s] = (int)x;
						vsamp[s] = (int)y;

						weight[s] = 1.0f / (1.0f + (float)Math.Sqrt(dx * dx + dy * dy));
						s++;
					}
				}

				for (int v = 0; v < bmp2.Height ;  v++)
				{
					for (int u = 0; u < bmp2.Width ;  u++)
					{
						float avgalpha = 0.0f;
						float avgred = 0.0f;
						float avggreen = 0.0f;
						float avgblue = 0.0f;
						// float totwei = 0.0f;

						for (int ss = 0; ss < samples ;  ss++)
						{
							int sx = u + usamp[ss] - imgx;
							int sy = v + vsamp[ss] - imgy;
							if (sx >= 0 && sy >= 0 && sx < bmp.Width && sy < bmp.Height)
							{
								Color c = bmp.GetPixel(sx, sy);
								// totwei += weight[ss];
								avgalpha += (float)c.A;// *weight[ss];
								avgred += c.R;
								avggreen += c.G;
								avgblue += c.B;
							}
						}

						avgalpha /= (float)samples;
						avgred /= (float)samples;
						avggreen /= (float)samples;
						avgblue /= (float)samples;

						/*-
						if (avgalpha < 0.0f)
							avgalpha = 0.0f;
						if (avgalpha >= 255.0f)
							avgalpha = 255.0f;
						  -*/
						bmp2.SetPixel(u, v, Color.FromArgb((int)avgalpha, (int)avgred, (int)avggreen, (int)avgblue));
					}
				}

				     return bmp2;
			}
			     return bmp;
		}
	}
}





